package com.wzh.core.utils;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;

import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * @description: 请求参数类型转换工具类
 * @author: wangzouhuax
 */
public class TypeUtils {

    private static final Gson gson = new GsonBuilder().create();

    /**
     * 将请求参数为基本类型的转换为包装类型
     */
    public static Class<?> cast(Class<?> clazz) {
        if (Objects.isNull(clazz)) {
            return null;
        }
        // 判断是否是基本类型
        if (clazz.isPrimitive()) {
            // 基本类型转换为包装类型
            if (clazz == int.class) {
                return Integer.class;
            } else if (clazz == long.class) {
                return Long.class;
            } else if (clazz == short.class) {
                return Short.class;
            } else if (clazz == char.class) {
                return Character.class;
            } else if (clazz == byte.class) {
                return Byte.class;
            } else if (clazz == float.class) {
                return Float.class;
            } else if (clazz == double.class) {
                return Double.class;
            } else if (clazz == boolean.class) {
                return Boolean.class;
            }
        }
        return clazz;
    }


    /**
     * 请求参数为实体对象中属性参数处理
     */
    public static Object[] processArgs(Method method, Object[] args, Type[] genericParameterTypes) {
        if (Objects.isNull(args) || args.length == 0) {
            return args;
        }
        Object[] result = new Object[args.length];
        for (int i = 0; i < args.length; i++) {
            result[i] = cast(method.getParameterTypes()[i], args[i], genericParameterTypes[i]);
        }
        return result;
    }

    /**
     * 处理参数
     *
     * @param parameterTypes        方法参数类型
     * @param original              原始类型
     * @param genericParameterType 方法参数泛型类型
     * @return 转换后的对象
     */
    public static Object cast(Class<?> parameterTypes, Object original, Type genericParameterType) {
        if (Objects.isNull(original)) {
            return original;
        }
        // 判断是否是基本类型
        if (parameterTypes.isPrimitive()) {
            try {
                // 基本类型转换为包装类型
                if (parameterTypes == int.class) {
                    return Integer.valueOf(original.toString());
                } else if (parameterTypes == long.class) {
                    return Long.valueOf(original.toString());
                } else if (parameterTypes == short.class) {
                    return Short.valueOf(original.toString());
                } else if (parameterTypes == char.class) {
                    return original.toString().charAt(0);
                } else if (parameterTypes == byte.class) {
                    return Byte.valueOf(original.toString());
                } else if (parameterTypes == float.class) {
                    return Float.valueOf(original.toString());
                } else if (parameterTypes == double.class) {
                    return Double.valueOf(original.toString());
                } else if (parameterTypes == boolean.class) {
                    return Boolean.valueOf(original.toString());
                }
            } catch (NumberFormatException e) {
                // 处理转换异常，例如打印日志、返回默认值等
                System.err.println("转换异常: " + e.getMessage());
                // 根据实际情况处理，这里举例返回null
                return null;
            }
        }
        // 泛型类型转换为原始类型
        String json = gson.toJson(original);
        // isAssignableFrom - 判断是否表示List的接口类型
        if (List.class.isAssignableFrom(parameterTypes)) {
            // 判断 genericParameterType 类型是否是泛型参数类型
            if (genericParameterType instanceof ParameterizedType parameterizedType) {
                Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
                TypeToken<?> parameterized = TypeToken.getParameterized(List.class, actualTypeArguments);
                return  gson.fromJson(json, parameterized);
            }
        }
        if (Map.class.isAssignableFrom(parameterTypes)) {
            if (genericParameterType instanceof ParameterizedType parameterizedType) {
                Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
                TypeToken<?> parameterized = TypeToken.getParameterized(Map.class, actualTypeArguments);
                return gson.fromJson(json, parameterized);
            }
        }
        return gson.fromJson(gson.toJson(original), parameterTypes);
    }
}
